import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { Minimatch } from 'minimatch'

const __filename    = fileURLToPath(import.meta.url)
const __dirname     = path.dirname(__filename)

// 目录配置
const postsDir      = path.resolve(__dirname, 'docs/posts')
const vitepressDir  = path.resolve(__dirname, '.vitepress')
const sidebarFile   = path.join(vitepressDir, 'sidebar.ts')

// 1. 读取排除规则 exclude.json
const excludeConfig = JSON.parse(
  fs.readFileSync(path.resolve(__dirname, 'exclude.json'), 'utf-8')
)
const {
  excludeDirs     = [],
  excludeFiles    = [],
  excludePatterns = []
} = excludeConfig
const excludeMatchers = excludePatterns.map(p => new Minimatch(p))

// 2. 读取优先级配置 priority.json
const priorityConfig = JSON.parse(
  fs.readFileSync(path.resolve(__dirname, 'priority.json'), 'utf-8')
)
const priorityOrder = Array.isArray(priorityConfig.order)
  ? priorityConfig.order
  : []

// 3. 保证 .vitepress 文件夹存在
if (!fs.existsSync(vitepressDir)) {
  fs.mkdirSync(vitepressDir, { recursive: true })
}

// 4. 判断是否应排除
function shouldExclude(relPath, name, isDir) {
  // a) 精确按目录名排除
  if (isDir && excludeDirs.includes(name)) return true
  // b) 精确按文件名排除
  if (!isDir && excludeFiles.includes(name)) return true
  // c) 通配符匹配
  const posixPath = relPath.replace(/\\/g, '/')
  for (const mm of excludeMatchers) {
    if (mm.match(posixPath)) return true
  }
  return false
}

// 5. 递归生成 sidebar
function walkDir(dir) {
  const entries = fs.readdirSync(dir, { withFileTypes: true })

  // 先过滤
  let filtered = entries.filter(entry => {
    const fullPath    = path.join(dir, entry.name)
    const relToPosts  = path.relative(postsDir, fullPath)
    const isDir       = entry.isDirectory()
    // 只保留目录和合法 md 文件（排除 README.md）
    if (!isDir) {
      if (!entry.name.endsWith('.md') || entry.name === 'README.md') {
        return false
      }
    }
    // 再按用户排除规则
    if (shouldExclude(relToPosts, entry.name, isDir)) {
      return false
    }
    return true
  })

  // 再排序：优先级列表排前面，同级再目录优先、再名称排序
  filtered.sort((a, b) => {
    const aPath = path.relative(postsDir, path.join(dir, a.name)).replace(/\\/g, '/')
    const bPath = path.relative(postsDir, path.join(dir, b.name)).replace(/\\/g, '/')
    // 取在 priorityOrder 中的索引
    let aIdx = priorityOrder.indexOf(aPath)
    let bIdx = priorityOrder.indexOf(bPath)
    // 如果是 md 文件，也可以尝试去掉后缀匹配（如 priority 列表不带 .md）
    if (aIdx === -1 && !a.isDirectory()) {
      aIdx = priorityOrder.indexOf(aPath.replace(/\.md$/, ''))
    }
    if (bIdx === -1 && !b.isDirectory()) {
      bIdx = priorityOrder.indexOf(bPath.replace(/\.md$/, ''))
    }
    // 都不在列表里则 aIdx/bIdx 为 -1，将它们置为 Infinity
    if (aIdx === -1) aIdx = Infinity
    if (bIdx === -1) bIdx = Infinity
    if (aIdx !== bIdx) return aIdx - bIdx

    // 优先级相同，目录优先
    if (a.isDirectory() && !b.isDirectory()) return -1
    if (!a.isDirectory() && b.isDirectory()) return 1
    // 同类型按中文名称排序
    return a.name.localeCompare(b.name, 'zh-CN')
  })

  // 最后映射到 sidebar item
  return filtered.map(entry => {
    const fullPath   = path.join(dir, entry.name)
    const relToPosts = path.relative(postsDir, fullPath).replace(/\\/g, '/')
    const linkPath   = '/' +
      path.join('docs/posts', relToPosts)
          .replace(/\\/g, '/')
          .replace(/\.md$/, '')

    if (entry.isDirectory()) {
      return {
        text:      entry.name,
        collapsed: true,
        items:     walkDir(fullPath)
      }
    } else {
      return {
        text: entry.name.replace(/\.md$/, ''),
        link: linkPath
      }
    }
  })
}

// 6. 生成最终 sidebar 对象
const sidebar = [
  {
    text:      '文章',
    collapsed: false,
    items:     walkDir(postsDir)
  }
]

// 7. 输出为 TypeScript 文件
const content =
  `import type { DefaultTheme } from 'vitepress'\n\n` +
  `const sidebar: DefaultTheme.Sidebar = ${JSON.stringify(sidebar, null, 2)}\n\n` +
  `export default sidebar\n`

fs.writeFileSync(sidebarFile, content)
console.log('✅ sidebar.ts 生成成功！')
